# -*- coding: utf-8 -*-

from flask import current_app, abort
from mongoengine.queryset import queryset, Q
import requests
import json

from app.data_structures import NoAppVersion
from app.utils import safe_float, get_objectId
import app.redis_keys as rk
from app.third_party_api import btapi
from app.constants import (
    user_agents, MTU_TYPE, LOCALITY_APPEND_PRODUCTS,
    DEVICE_TYPES, STATISTICS_CATEGORIES
)
from app.models import (
    KV, PlanOrderMtu, Mtu, Product,
    MtuComment, Destination, DestinationInfo,
    DeviceId, Statistics, Order
)


def get_users_info():
    return {}


def get_object_or_404(Klass, id):
    id = get_objectId(id)
    if not id:
        abort(404)

    obj = Klass.objects.filter(id=id).first()
    if not obj:
        abort(404)

    return obj


def get_object_or_None(Klass, id):
    id = get_objectId(id)
    if not id:
        return None

    obj = Klass.objects.filter(id=id).first()
    if not obj:
        return None

    return obj


def get_mtu_comments_info(mtu_comments):
    """
    获取mtu 评论详情
    """
    user_ids = set(x.user_id for x in mtu_comments)
    users_info = btapi.get_user_infos(user_ids)
    items = []

    for m in mtu_comments:
        items.append({
            'user': users_info.get(m.user_id),
            'content': m.text,
            'rating': m.score,
            'id': m.pk,
            'datetime': m.date_added.strftime('%Y-%m-%d %H:%M:%S'),
        })
    return {
        'tips': items,
    }


def get_mtu_comments(mtu, start=0, count=20):
    """
    获取mtu 评论
    """
    condition = Q(mtu=mtu, is_active=True)
    total_count = MtuComment.objects.filter(condition).count()
    tips = {}
    ret = {
        'tips': [],
    }

    if start < total_count:
        mtu_comments = MtuComment.objects.filter(
            mtu=mtu, is_active=True)[start:start + count + 1]
        ret['next_start'] = start + count if mtu_comments.count() > count else None
        ret['tips'].extend(get_mtu_comments_info(mtu_comments)['tips'])

    if tips:
        ret['next_start'] = tips['next_start']
        ret['tips'].extend(tips['tips'])
    ret['total_count'] = total_count
    return ret


def get_user_agent(request):
    args = request.args
    result = int(args.get("landing_page", user_agents.DEFAULT))
    user_agent = request.headers.get('HTTP_USER_AGENT', "").lower()

    map_dict = {
        "iphone": user_agents.IPHONE,
        "ipad": user_agents.IPAD,
        "ipod": user_agents.IPOD,
        "android": user_agents.ANDROID,
    }

    key = None
    for e in map_dict.keys():
        if e in user_agent:
            key = e
            break

    if not result:
        result = map_dict.get(key, 0)

    return result


def api_paginate_queryset(request, querylist):
    getter = request.args.get
    start = getter('start', 0, type=int)
    count = getter('count', 20, type=int)

    if isinstance(querylist, queryset.QuerySet):
        result = querylist.skip(start).limit(count)
        if result.count() <= count:
            next_start = None
        else:
            next_start = (start + count)
        return result, next_start
    else:
        return [], None


def get_database_version(request, name_en=None, db_version=None):
    #  setting in middleware BreadtripSessionMiddleware
    from app.models import Locality

    app_version = request.breadtrip.version
    if request.breadtrip.version != NoAppVersion():
        if app_version.android:
            app_version = app_version.android
        elif app_version.ios:
            app_version = app_version.ios
        else:
            app_version = '2.0.0'
    else:
        app_version = '2.0.0'

    user_agent = get_user_agent(request)
    key = 'android' if user_agent == user_agents.ANDROID else 'ios'
    data = KV.get(rk.VACATION_DATABASE_VERSION) or {}

    if current_app.config.get('RUN_AS_DEV'):
        version_key = rk.LOCALITY_DATABASE_VERSION_DEV
    else:
        version_key = rk.LOCALITY_DATABASE_VERSION

    version_items = KV.get(version_key) or {}
    ret = {}

    if name_en:
        names = [name_en]
    else:
        names = [x.name_en for x in Locality.objects.filter(published=True)]

    for name in names:
        value = data.get(name)
        app = app_version.split('.')
        for item in version_items.get(name, []):
            k = item['app_version'].split('.')
            if int(k[0]) > int(app[0]) or (int(k[0]) == int(app[0]) and
                                                   int(k[1]) > int(app[1])) or (int(k[0]) == int(app[0]) and
                                                                                        int(k[1]) == int(
                                                                                        app[1]) and int(k[2]) >= int(
                app[2])):
                value = item[key]
                break
        ret[name] = {
            'database_version': value,
            'download_url': ('http://vacation.breadtrip.com/download_database/'
                             '?db_version=%s&name=%s' %
                             (value, name)) if value else ''
        }

    # 检查是否有数据库版本更新
    if name_en and db_version:
        ret[name_en].update({
            'changed': False,
            'new_version': db_version,
            'compatible': False,
            'prompt': u'数据库没有更新',
        })
        if not value or (db_version == value and value != data.get(name_en)):
            changed = True if db_version != data.get(name_en) else False
            ret[name_en].update(new_version=data.get(name_en), changed=changed,
                                prompt=u'建议升级新版app')
        elif value and db_version < value:
            ret[name_en].update(new_version=value, changed=True, compatible=True,
                                prompt=u'有新版本，增加了更多好玩的地方, 建议升级')
    return ret


def get_localities_temp(localities):
    temps = {}
    for locality in localities:
        retries = 3
        temp_url = 'http://api.openweathermap.org/data/2.5/weather?lat=%s&lon=%s'
        coordinates = locality.location['coordinates']
        temp_url = temp_url % (coordinates[1], coordinates[0])
        temp = 0
        for i in xrange(retries):
            r = requests.get(temp_url)
            if r.status_code == requests.codes.ok:
                data = json.loads(r.text)
                temp = data.get('main', {}).get('temp')
                if temp:
                    temps[locality.pk] = round(safe_float(temp) - 273.15, 1)
                    break
    return temps


def save_plan_order_mtus(plan, mtus):
    special_ids = []
    condition = Q(id__in=[x.destination.id for x in mtus])
    dests = Destination.objects.filter(condition)
    locality_ids = [x.locality_id for x in dests]
    for locality_id in locality_ids:
        special_ids.extend(LOCALITY_APPEND_PRODUCTS.get(locality_id, []))

    items = PlanOrderMtu.objects.filter(plan=plan, mtu__in=mtus)
    for item in items.filter(is_active=True):
        item.is_active = False
        item.save()

    for mtu in mtus:
        item = items.filter(mtu=mtu, is_active=False)
        if item:
            item = item[0]
            item.is_active = True
        else:
            dest = dests.get(id=mtu.destination.id)
            is_special = True if mtu.target_type == MTU_TYPE.PRODUCT and \
                                 mtu.target_id in special_ids else False
            item = PlanOrderMtu(plan=plan, mtu=mtu, destination=dest,
                                is_special=is_special)
        item.save()
    return items


def update_or_create_device(request, device_id=None, **kwargs):
    if not device_id:
        device_id = request.headers.get('HTTP_VACATION_DEVICE_ID', None)
    if not device_id:
        return None

    user_agent = get_user_agent(request)
    if user_agent == user_agents.ANDROID:
        device = DEVICE_TYPES.ANDROID
    else:
        device = DEVICE_TYPES.IOS

    try:
        condition = Q(device_id=device_id)
        obj = DeviceId.objects(condition).modify(upsert=True,
                                                 new=True,
                                                 set__device_id=device_id)

        obj.device = device
    except:
        condition = Q(device_id=device_id, device=device)
        devices = DeviceId.objects.filter(condition).order_by('date_added')
        if not devices:
            return None

        obj = list(devices)[-1]
        for device in list(devices)[:-1]:
            device.delete()

    obj.__dict__.update(kwargs)
    obj.save()
    for k, v in kwargs.items():
        if not v or k == 'is_flight' or k == 'source':
            continue
        category = getattr(STATISTICS_CATEGORIES, k.upper())
        condition = Q(device=obj, category=category)
        obj = Statistics.objects(condition).modify(upsert=True,
                                                   new=True,
                                                   set__device=device,
                                                   set__category=category)
    return obj


def get_order_info(order):
    return {}


def get_plan_orders_info_v2(plan):
    """
    获取计划的订单信息(MTU api)
    分别是hotel以及product
    """
    exceed_fee = {
        '88': 118,
    }
    pom_condition = Q(is_active=True, plan=plan)
    ordermtus = PlanOrderMtu.objects.filter(pom_condition).order_by('-is_special', 'destination')
    mtus = Mtu.objects.filter(id__in=set(x.mtu_id for x in ordermtus))

    product_ids = [x.target_id for x in mtus.filter(target_type=MTU_TYPE.PRODUCT)]
    product_condition = Q(id__in=product_ids)
    products = Product.objects.filter(product_condition)
    orders = Order.objects.filter(pk__in=[x.order_id for x in ordermtus])

    data = {
        'products': [],
        'hotels': [],
        'is_share': plan.is_share,
    }

    for ordermtu in ordermtus:
        mtu = mtus.filter(id=ordermtu.mtu_id).first()

        # products
        product = products.get(pk=mtu.target_id)
        item = {
            'name': product.name,
            'mtu_id': mtu.pk,
            'is_booking': mtu.is_booking,
            'destination_id': mtu.destination_id,
            'currency ': 'CNY',
        }
        category_id = 16 if product.template_id == 6 else 7 if \
            product.template_id == 5 else product.category_id
        item.update({
            'template_id': product.template_id,
            'exceed_fee': exceed_fee.get(product.pk, 0),
            'is_can_book': True,
            'category_id': category_id,
            'time_summary': product.time_title,
        })
        order = None
        if orders.filter(pk=ordermtu.order_id):
            order = orders.get(pk=ordermtu.order_id)
        if order and order.status == 1:
            item.update(get_order_info(order))
        else:
            info = get_product_order_info(product, plan)
            ordermtu.order = info['order']
            ordermtu.save()
            del info['order']
            item.update(info)
        data['products'].append(item)
    return data


def get_product_order_info(product, plan, date=None):
    """
    单个产品生成订单
    """
    return {}


def get_destination_info(destination):
    item = {}

    if destination:
        location = destination.location
        if isinstance(location, dict):
            coordinates = location['coordinates']
            longitude, latitude = coordinates[0], coordinates[1]
        elif isinstance(location, tuple):
            longitude, latitude = location[0], location[1]
        else:
            longitude, latitude = 0, 0

        item = dict(
            longitude=longitude,
            latitude=latitude,
            name=destination.name,
            locality_id=str(destination.locality.id),
        )

        condition = Q(destination=destination.id)
        destination_info = DestinationInfo.objects.filter(condition).first()
        if destination_info:
            tags = [e.name for e in destination_info.tags]
            item['max_days'] = destination_info.max_days
            item['min_days'] = destination_info.min_days
            item['periphery'] = destination_info.periphery
            item['tags'] = tags
            item['images'] = destination_info.images

    return item


def paginate_queryset(args, querylist):
    page = args.get('page', 1, type=int)
    rows = args.get('rows', 20, type=int)
    start = (page - 1) * rows
    if isinstance(querylist, queryset.QuerySet):
        result = querylist.skip(start).limit(rows).order_by('position')
    else:
        result = []

    return result


def upload_image_func(image):
    # TO DO
    return dict(
        status=0,
        message='',
        data=dict(
            url="http://breadtripimages.qiniudn.com/covers_2015_10_14"
                "_abcdd1c41c37d552642c095de3ea5d99.jpg?imageView/2/w/960/q/85"
        )
    )
